using Godot;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.NetworkInformation;
using System.Numerics;
using TopDownGodot.Src.Globals.Multiplayer;

namespace TopDownGodot.Src.Game
{
    public partial class CharacterChoices : Node
    {
        private int _characterId;
        private List<AnimatedSprite2D> _playerAnimatedArray = new List<AnimatedSprite2D>();
        private List<ColorRect> _playerColorRectArray = new List<ColorRect>();
        [Export]
        public Godot.Collections.Dictionary PeerStateDictionary = new Godot.Collections.Dictionary(); // peer_id -> state_index

        private const string SCENE_STRING = "res://scene/main.tscn";

        public override void _Ready()
        {
            if (Multiplayer.IsServer())
                PeerResourceLoader();

            AnimatedInitialization();
            StateColorInitialization();

            Multiplayer.PeerConnected += OnPeerConnected;
            Multiplayer.PeerDisconnected += OnPeerDisconnected;

            if (!MultiplayerGlobal.IsMultiplayer)
                GetNode<Control>("GUI").Visible = false;
        }

        public override void _Process(double delta)
        {
            var progress = new Godot.Collections.Array();
            _ = ResourceLoader.LoadThreadedGetStatus(SCENE_STRING, progress);
            // Can print state/progress for debugging if needed
        }

        [Rpc(MultiplayerApi.RpcMode.Authority, CallLocal = true, TransferMode = MultiplayerPeer.TransferModeEnum.Unreliable)]
        public static void PeerResourceLoader()
        {
            ResourceLoader.LoadThreadedRequest(SCENE_STRING);
        }

        public void OnSelect1ButtonUp()
        {
            AnimatedSpriteStop();
            _characterId = 1;
            _playerAnimatedArray[0].Play();
        }

        public void OnSelect2ButtonUp()
        {
            AnimatedSpriteStop();
            _characterId = 2;
            _playerAnimatedArray[1].Play();
        }

        public void OnSelect3ButtonUp()
        {
            AnimatedSpriteStop();
            _characterId = 3;
            _playerAnimatedArray[2].Play();
        }

        public void OnConfirmButtonUp()
        {
            if (Multiplayer.IsServer())
                UpdateConfirmStateColor(Multiplayer.GetUniqueId());
            else
                RpcId(1, nameof(UpdateConfirmStateColor), Multiplayer.GetUniqueId());

            if (CheckAllPlayersConfirmed() && Multiplayer.IsServer())
                Rpc(nameof(ChangeSceneToGame));
        }

        [Rpc(MultiplayerApi.RpcMode.Authority, CallLocal = true, TransferMode = MultiplayerPeer.TransferModeEnum.Reliable)]
        public void ChangeSceneToGame()
        {
            EmitSignal(nameof(MultiplayerGlobal.SendCharacterIdEventHandler), _characterId);
            //MultiplayerGlobal.SendCharacterIdEventHandler.(_characterId);
            var gamePacked = ResourceLoader.LoadThreadedGet(SCENE_STRING) as PackedScene;
            GetTree().ChangeSceneToPacked(gamePacked);
        }

        public void AnimatedInitialization()
        {
            foreach (Node node in GetChildren())
            {
                if (node.Name.ToString().Contains("Player"))
                {
                    var playerCharacterBody = node.GetNode<AnimatedSprite2D>("PlayerAnimatedSprite");
                    playerCharacterBody.Stop();
                    _playerAnimatedArray.Add(playerCharacterBody);
                }
            }
        }

        public void AnimatedSpriteStop()
        {
            foreach (var animated in _playerAnimatedArray)
                animated.Stop();
        }

        public void StateColorInitialization()
        {
            _playerColorRectArray.Add(GetNode<ColorRect>("GUI/Player1/State"));
            _playerColorRectArray.Add(GetNode<ColorRect>("GUI/Player2/State"));
            _playerColorRectArray.Add(GetNode<ColorRect>("GUI/Player3/State"));
            _playerColorRectArray.Add(GetNode<ColorRect>("GUI/Player4/State"));

            // Initialize all states as red
            foreach (var rect in _playerColorRectArray)
                rect.Color = Colors.Red;

            // Server occupies the first slot
            if (Multiplayer.IsServer())
                AssignStateToPeer(1, 0); // Server ID is 1, use the first ColorRect
        }

        public void OnPeerConnected(long id)
        {
            Rpc(nameof(PeerResourceLoader));
            if (Multiplayer.IsServer())
            {
                for (int i = 0; i < _playerColorRectArray.Count; i++)
                {
                    if (!PeerStateDictionary.Values.Contains(i))
                    {
                        AssignStateToPeer((int)id, i);
                        break;
                    }
                }
            }
        }

        public void OnPeerDisconnected(long id)
        {
            if (Multiplayer.IsServer())
            {
                Variant idVariant = Variant.CreateFrom(id);
                var stateIndex = PeerStateDictionary.ContainsKey(idVariant) ? (int?)PeerStateDictionary[idVariant].AsInt32() : null;
                if (stateIndex != null)
                {
                    _playerColorRectArray[stateIndex.Value].Color = Colors.Red;
                    PeerStateDictionary.Remove(idVariant);
                    Rpc(nameof(SyncStateColors), GetCurrentColorStates());
                }
            }
        }

        public void AssignStateToPeer(int peerId, int stateIndex)
        {
            _playerColorRectArray[stateIndex].Color = Colors.White;
            PeerStateDictionary[peerId] = stateIndex;
            GD.Print($"对等体的状态 {peerId}: {stateIndex}");
            Rpc(nameof(SyncStateColors), GetCurrentColorStates());
        }

        [Rpc(CallLocal = true, TransferMode = MultiplayerPeer.TransferModeEnum.Reliable)]
        public void UpdateConfirmStateColor(long peerId)
        {
            if (Multiplayer.IsServer())
            {
                int? stateIndex = PeerStateDictionary.ContainsKey(peerId) ? (int?)PeerStateDictionary[peerId] : null;
                if (stateIndex != null)
                {
                    _playerColorRectArray[stateIndex.Value].Color = Colors.Green;
                    Rpc(nameof(SyncStateColors), GetCurrentColorStates());
                }
                GD.Print($"玩家: {peerId} 确认选择!");
            }
        }

        [Rpc(CallLocal = false, TransferMode = MultiplayerPeer.TransferModeEnum.Reliable)]
        public void SyncStateColors(Godot.Collections.Array colorStates)
        {
            int count = Math.Min(_playerColorRectArray.Count, colorStates.Count);
            for (int i = 0; i < count; i++)
            {
                _playerColorRectArray[i].Color = (Color)colorStates[i];
            }
        }

        public bool CheckAllPlayersConfirmed()
        {
            bool allConfirmed = true;
            foreach (var stateIndexObj in PeerStateDictionary.Values)
            {
                int stateIndex = Convert.ToInt32(stateIndexObj);
                if (_playerColorRectArray[stateIndex].Color != Colors.Green)
                {
                    allConfirmed = false;
                    break;
                }
            }

            if (allConfirmed && PeerStateDictionary.Count > 0)
            {
                GD.Print("所有玩家都已确认选择！");
                return true;
            }
            return false;
        }

        public Godot.Collections.Array GetCurrentColorStates()
        {
            var colors = new Godot.Collections.Array();
            foreach (var rect in _playerColorRectArray)
                colors.Add(rect.Color);
            return colors;
        }

        // 待修改
        public void OnButtonButtonUp()
        {
            GetTree().ChangeSceneToFile("res://scence/main.tscn");
        }
    }
}